home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / DCPSYS.C < prev    next >
C/C++ Source or Header  |  1991-12-07  |  21KB  |  661 lines

  1. /*
  2.    For best results in visual layout while viewing this file, set
  3.    tab stops to every 4 columns.
  4. */
  5.  
  6. /*
  7.    dcpsys.c
  8.  
  9.    Revised edition of dcp
  10.  
  11.    Stuart Lynne May/87
  12.  
  13.    Copyright (c) Richard H. Lamb 1985, 1986, 1987
  14.    Changes Copyright (c) Stuart Lynne 1987
  15.    Changes Copyright (c) Andrew H. Derbyshire 1989, 1990
  16.  
  17.    Updated:
  18.  
  19.       13May89  - Modified checkname to only examine first token of name.
  20.                  Modified rmsg to initialize input character before use.
  21.                  - ahd
  22.       16May89  - Moved checkname to router.c - ahd
  23.       17May89  - Wrote real checktime() - ahd
  24.       17May89  - Changed getsystem to return 'I' instead of 'G'
  25.       25Jun89  - Added Reach-Out America to keyword table for checktime
  26.       22Sep89  - Password file support for hosts
  27.       25Sep89  - Change 'ExpectStr' message to debuglevel 2
  28.       01Jan90  - Revert 'ExpectStr' message to debuglevel 1
  29.       28Jan90  - Alter callup() to use table driven modem driver.
  30.                  Add direct(), qx() procedures.
  31.       8 Jul90  - Add John DuBois's expectstr() routine to fix problems
  32.                  with long input buffers.
  33.       11Nov90  - Delete QX support, add ddelay, ssleep calls
  34. */
  35.  
  36. /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
  37.  
  38.  
  39. /* Support routines */
  40.  
  41. /*--------------------------------------------------------------------*/
  42. /*                        system include files                        */
  43. /*--------------------------------------------------------------------*/
  44.  
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <time.h>
  49. #include <ctype.h>
  50. #include <assert.h>                                                  /* ahd */
  51.  
  52. /*--------------------------------------------------------------------*/
  53. /*                    UUPC/extended include files                     */
  54. /*--------------------------------------------------------------------*/
  55.  
  56. #include "lib.h"
  57. #include "arpadate.h"
  58. #include "checktim.h"
  59. #include "dcp.h"
  60. #include "dcpfpkt.h"
  61. #include "dcpgpkt.h"
  62. #include "dcplib.h"
  63. #include "dcpsys.h"
  64. #include "hlib.h"
  65. #include "hostable.h"
  66. #include "modem.h"
  67. #include "nbstime.h"
  68. #include "ndir.h"
  69. #include "security.h"
  70. #include "ulib.h"
  71.  
  72. currentfile();
  73.  
  74. #define  PROTOS   "gf"        /* available protocols */
  75. #define MSGTIME 20            /* Timeout for many operations */
  76.  
  77. Proto Protolst[] = {
  78.    'g', ggetpkt, gsendpkt, gopenpk, gclosepk,
  79.         grdmsg,  gwrmsg,   geofpkt, gfilepkt,
  80.    'f', fgetpkt, fsendpkt, fopenpk, fclosepk,
  81.         frdmsg,  fwrmsg,   feofpkt, ffilepkt,
  82.    '\0'};
  83.  
  84. procref  getpkt, sendpkt, openpk, closepk, rdmsg, wrmsg, eofpkt, filepkt;
  85.  
  86. char *flds[60];
  87. int kflds;
  88. static char protocols[5];
  89. static char S_sysline[BUFSIZ];
  90.  
  91. static void setproto(char wanted);
  92.  
  93. /****************************************/
  94. /*              Sub Systems             */
  95. /****************************************/
  96.  
  97. /*--------------------------------------------------------------------*/
  98. /*    g e t s y s t e m                                               */
  99. /*                                                                    */
  100. /*    Process a systems file (L.sys) entry.                           */
  101. /*    Null lines or lines starting with '#' are comments.             */
  102. /*--------------------------------------------------------------------*/
  103.  
  104. CONN_STATE getsystem()
  105. {
  106.    do {  /* flush to next non-comment line */
  107.       if (fgets(S_sysline, BUFSIZ, fsys) == nil(char))
  108.          return CONN_EXIT;
  109.    } while ((*S_sysline == '\0') || (*S_sysline == '\n') || (*S_sysline == '#'));
  110.  
  111.    printmsg(8, "sysline=\"%s\"", S_sysline);
  112.  
  113.    kflds = getargs(S_sysline, flds);
  114.    strcpy(rmtname, flds[FLD_REMOTE]);
  115.    strcpy(protocols, flds[FLD_PROTO]);
  116.  
  117.    if (debuglevel >= 4) {
  118.       int   i;
  119.       for (i = FLD_EXPECT; i < kflds; i += 2)
  120.          printmsg(6, "expect [%02d]:\t%s\nsend   [%02d]:\t%s",
  121.             i, flds[i], i + 1, flds[i + 1]);
  122.    }
  123.  
  124.    printmsg(2,
  125.           "remote=%s, call-time=%s, device=%s, telephone=%s, protocol=%s",
  126.           rmtname, flds[FLD_CCTIME], flds[FLD_TYPE], flds[FLD_PHONE],
  127.           protocols);
  128.  
  129.    fwork = nil(FILE);
  130.    if (
  131.          !calledhost(rmtname) &&
  132.          (
  133.             equal(Rmtname, "all") ||
  134.             equal(Rmtname, rmtname) ||
  135.             (
  136.                equal(Rmtname, "any") && (scandir(rmtname) == XFER_REQUEST)
  137.             )
  138.          )
  139.        )
  140.     {
  141.  
  142.       if (fwork != nil(FILE)) /* in case matched with scandir     */
  143.          fclose(fwork);
  144.       scandir( NULL );        /* Reset directory search as well   */
  145.       hostp = checkreal( rmtname );
  146.       checkref( hostp );
  147.  
  148.       securep = GetSecurity( hostp );
  149.       if ( securep == NULL )
  150.       {
  151.          printmsg(0,"getsystem: system \"%s\" not defined in \
  152. PERMISSIONS file", hostp->hostname);
  153.          return CONN_INITIALIZE;
  154.       }
  155.  
  156.       memset( &remote_stats, 0, sizeof remote_stats);
  157.       return CONN_CALLUP;    /* startup this system */
  158.  
  159.    } else
  160.       return CONN_INITIALIZE;    /* Look for next system to process   */
  161.  
  162. } /*getsystem*/
  163.  
  164. /*--------------------------------------------------------------------*/
  165. /*    s y s e n d                                                     */
  166. /*                                                                    */
  167. /*    End UUCP session negotiation                                    */
  168. /*--------------------------------------------------------------------*/
  169.  
  170. CONN_STATE sysend()
  171. {
  172.    char msg[80];
  173.  
  174.    if (hostp->hstatus == inprogress)
  175.       hostp->hstatus = succeeded;
  176.  
  177.    msg[1] = '\0';
  178.       wmsg("OOOOOO", TRUE);
  179.       if (rmsg(msg, TRUE, 5) == TIMEOUT)
  180.          goto hang;
  181. hang:
  182.    wmsg("OOOOOO", TRUE);
  183.  
  184.  
  185.    return CONN_DROPLINE;
  186. } /*sysend*/
  187.  
  188.  
  189. /*
  190.    w m s g
  191.  
  192.    write a ^P type msg to the remote uucp
  193. */
  194.  
  195. void wmsg(char *msg, const boolean synch)
  196. {
  197.  
  198.    if (synch)
  199.       swrite("\0\020", 2);
  200.  
  201.    swrite(msg, strlen(msg));
  202.  
  203.    if (synch)
  204.       swrite("\0", 1);
  205.  
  206. } /*wmsg*/
  207.  
  208.  
  209. /*
  210.    r m s g
  211.  
  212.    read a ^P msg from UUCP
  213. */
  214.  
  215. int rmsg(char *msg, const boolean synch, unsigned int msgtime)
  216. {
  217.    int i;
  218.    static int max_len = 60;
  219.    char ch = '?';       /* Initialize to non-zero value  */    /* ahd   */
  220.  
  221. /*--------------------------------------------------------------------*/
  222. /*                        flush until next ^P                         */
  223. /*--------------------------------------------------------------------*/
  224.  
  225.    if (synch == 1)
  226.    {
  227.       do {
  228.          if (sread(&ch, 1, msgtime) < 1)
  229.             return TIMEOUT;
  230.  
  231.       } while ((ch & 0x7f) != '\020');
  232.    }
  233.  
  234. /*--------------------------------------------------------------------*/
  235. /*   Read until timeout, next newline, or we fill the input buffer    */
  236. /*--------------------------------------------------------------------*/
  237.  
  238.    for (i = 0; (i < max_len) && (ch != '\0'); ) {
  239.       if (sread(&ch, 1, msgtime) < 1)
  240.          return TIMEOUT;
  241.       if ( synch == 2 )
  242.          swrite( &ch, 1);
  243.       ch &= 0x7f;
  244.       if (ch == '\r' || ch == '\n')
  245.          ch = '\0';
  246.       msg[i++] = ch;
  247.    }
  248.  
  249.    msg[max_len - 1] = '\0';
  250.    return strlen(msg);
  251.  
  252. } /*rmsg*/
  253.  
  254.  
  255. /*--------------------------------------------------------------------*/
  256. /*    s t a r t u p _ s e r v e r                                     */
  257. /*                                                                    */
  258. /*    Exchange host and protocol information for a system we called   */
  259. /*--------------------------------------------------------------------*/
  260.  
  261. CONN_STATE startup_server()
  262. {
  263.    char msg[80];
  264.    char *s;
  265.  
  266. /*--------------------------------------------------------------------*/
  267. /*    Handle the special case of '*' protocol, which is really our    */
  268. /*    NBS time setting support                                        */
  269. /*--------------------------------------------------------------------*/
  270.  
  271.    if (*protocols == '*')
  272.    {
  273.       if (nbstime())
  274.       {
  275.          didcall(rmtname);
  276.          hostp->hstatus = succeeded;
  277.          time( &hostp->hstats->lconnect );
  278.       }
  279.       return CONN_DROPLINE;
  280.    }
  281.  
  282. /*--------------------------------------------------------------------*/
  283. /*                      Begin normal processing                       */
  284. /*--------------------------------------------------------------------*/
  285.  
  286.    if (rmsg(msg, TRUE, PROTOCOL_TIME) == TIMEOUT)
  287.    {
  288.       printmsg(1,"Startup: Timeout for first message");
  289.       return CONN_TERMINATE;
  290.    }
  291.    printmsg(2, "1st msg = %s", msg);
  292.  
  293. /*--------------------------------------------------------------------*/
  294. /*              The first message must begin with Shere               */
  295. /*--------------------------------------------------------------------*/
  296.  
  297.    if (!equaln(msg,"Shere",5))
  298.    {
  299.       printmsg(1,"Startup: First message not Shere");
  300.       return CONN_TERMINATE;
  301.    }
  302.  
  303. /*--------------------------------------------------------------------*/
  304. /*    The host can send either a simple Shere, or Shere=hostname;     */
  305. /*    we allow either.                                                */
  306. /*--------------------------------------------------------------------*/
  307.  
  308.    if ((msg[5] == '=') && !equaln(&msg[6], rmtname, HOSTLEN))
  309.    {
  310.       printmsg(1,"Startup: Wrong host %s, expected %s",
  311.                &msg[6], rmtname);
  312.       hostp->hstatus = wrong_host;
  313.       return CONN_TERMINATE; /* wrong host */              /* ahd */
  314.    }
  315.  
  316.    /* sprintf(msg, "S%.7s -Q0 -x%d", nodename, debuglevel); */
  317.    /* -Q0 -x16 remote debuglevel set */
  318.    sprintf(msg, "S%s", securep->myname );
  319.    wmsg(msg, TRUE);
  320.  
  321. /*--------------------------------------------------------------------*/
  322. /*                  Second message is system is okay                  */
  323. /*--------------------------------------------------------------------*/
  324.  
  325.    if (rmsg(msg, TRUE, PROTOCOL_TIME) == TIMEOUT)
  326.    {
  327.       printmsg(1,"Startup: Timeout for second message");
  328.       return CONN_TERMINATE;
  329.    }
  330.  
  331.    printmsg(2, "2nd msg = %s", msg);
  332.    if (!equaln(&msg[1], "OK", 2))
  333.    {
  334.       printmsg(1,"Unexpected second message: %s",&msg[1]);
  335.       return CONN_TERMINATE;
  336.    }
  337.  
  338. /*--------------------------------------------------------------------*/
  339. /*                Third message is protocol exchange                  */
  340. /*--------------------------------------------------------------------*/
  341.  
  342.    if (rmsg(msg, TRUE, PROTOCOL_TIME) == TIMEOUT)
  343.       return CONN_TERMINATE;
  344.  
  345.    printmsg(2, "3rd msg = %s", msg);
  346.    if (*msg != 'P')
  347.    {
  348.       printmsg(1,"Unexpected third message: %s",&msg[1]);
  349.       return CONN_TERMINATE;
  350.    }
  351.  
  352. /*--------------------------------------------------------------------*/
  353. /*                      Locate a common procotol                      */
  354. /*--------------------------------------------------------------------*/
  355.  
  356.    s = strpbrk( protocols, &msg[1] );
  357.    if ( s == NULL )
  358.    {
  359.       printmsg(1,"Startup: No common protocol");
  360.       wmsg("UN", TRUE);
  361.       return CONN_TERMINATE; /* no common protocol */
  362.    }
  363.    else {
  364.       sprintf(msg, "U%s", s);
  365.       wmsg(msg, TRUE);
  366.    }
  367.  
  368.    setproto(*s);
  369.  
  370. /*--------------------------------------------------------------------*/
  371. /*    The connection is complete; report this and return to caller    */
  372. /*--------------------------------------------------------------------*/
  373.  
  374.    printmsg(0,"%s connected to host %s at %ld bps using %c protocol",
  375.          nodename, rmtname, (long) GetSpeed() , *s);
  376.  
  377.    hostp->hstatus = inprogress;
  378.                                                          /* ahd   */
  379.    didcall(rmtname);
  380.    return CONN_SERVER;
  381. } /*startup_server*/
  382.  
  383. /*--------------------------------------------------------------------*/
  384. /*    s t a r t u p _ c l i e n t                                     */
  385. /*                                                                    */
  386. /*    Setup a host connection with a system which has called us       */
  387. /*--------------------------------------------------------------------*/
  388.  
  389. CONN_STATE startup_client()
  390. {
  391.    char tmp1[20], tmp2[20];
  392.    char msg[80];
  393.  
  394. /*--------------------------------------------------------------------*/
  395. /*    Challange the host calling in with the name defined for this    */
  396. /*    login (if available) otherwise our regular node name.  (It's    */
  397. /*    a valid session if the securep pointer is NULL, but this is     */
  398. /*    trapped below in the call to ValidateHost()                     */
  399. /*--------------------------------------------------------------------*/
  400.  
  401.    sprintf(msg, "Shere=%s", securep == NULL ?
  402.                               nodename : securep->myname );
  403.    wmsg(msg, TRUE);
  404.  
  405.    if (rmsg(msg, TRUE, PROTOCOL_TIME) == TIMEOUT)
  406.       return CONN_TERMINATE;
  407.    sscanf(&msg[1], "%s %s %s", rmtname, tmp1, tmp2);
  408.    sscanf(tmp2, "-x%d", &debuglevel);
  409.    printmsg(2, "debuglevel set to %d by remote", debuglevel);
  410.    printmsg(2, "1st msg from remote = %s", msg);
  411.  
  412. /*--------------------------------------------------------------------*/
  413. /*                Verify the remote host name is good                 */
  414. /*--------------------------------------------------------------------*/
  415.  
  416.    hostp = checkreal( rmtname );
  417.    if ( hostp == BADHOST )
  418.    {
  419.       if (anonymous != NULL)
  420.       {
  421.          hostp = checkreal( ANONYMOUS_HOST );      /* Find dummy entry */
  422.          if ( hostp == BADHOST )       /* Was it there?              */
  423.             panic();                   /* No --> Drop wing, run in
  424.                                        circles like sky is falling*/
  425.          if (!checktime( anonymous , 0))     /* Good time to call?      */
  426.          {
  427.             wmsg("RLCK",TRUE);
  428.             return CONN_TERMINATE;
  429.          }    /* if */
  430.       }    /* if (anonymous != NULL) */
  431.       else {
  432.          wmsg("RYou are unknown to me",TRUE);
  433.          printmsg(0,"startup: Unknown host \"%s\"", rmtname);
  434.          return CONN_TERMINATE;
  435.       } /* else */
  436.    } /* if */
  437.  
  438.    if ( !ValidateHost( rmtname ))
  439.                                           /* Wrong host for user? */
  440.    {                                      /* Yes --> Abort        */
  441.       wmsg("RLOGIN",TRUE);
  442.       printmsg(0,"startup: Wrong host \"%s\", expected \"%s\"",
  443.             rmtname, hostp->hostname);
  444.       hostp->hstatus = wrong_host;
  445.       return CONN_TERMINATE;
  446.    } /* if */
  447.  
  448.    strcpy(rmtname,hostp->hostname);       /* Make sure we use the
  449.                                              full host name       */
  450.  
  451. /*--------------------------------------------------------------------*/
  452. /*                If we must call the user back, do so                */
  453. /*--------------------------------------------------------------------*/
  454.  
  455.    if (securep->callback)
  456.    {
  457.       wmsg("RCB",TRUE);
  458.       hostp->hstatus = callback_req;
  459.       return CONN_TERMINATE;  /* Really more complex than this       */
  460.    }
  461.  
  462. /*--------------------------------------------------------------------*/
  463. /*              The host name is good; get the protocol               */
  464. /*--------------------------------------------------------------------*/
  465.  
  466.    wmsg("ROK", TRUE);
  467.  
  468.    sprintf(msg, "P%s", PROTOS);
  469.    wmsg(msg, TRUE);
  470.  
  471.    if (rmsg(msg, TRUE, PROTOCOL_TIME) == TIMEOUT)
  472.       return CONN_TERMINATE;
  473.  
  474.    if (msg[0] != 'U')
  475.    {
  476.       printmsg(0,"Unexpected second message: %s", msg);
  477.       return CONN_TERMINATE;
  478.    }
  479.  
  480.    if (strchr(PROTOS, msg[1]) == nil(char))
  481.    {
  482.       printmsg(0,"startup: Host does not support our protocols");
  483.       return CONN_TERMINATE;
  484.    }
  485.  
  486.    setproto(msg[1]);
  487.  
  488. /*--------------------------------------------------------------------*/
  489. /*            Report that we connected to the remote host             */
  490. /*--------------------------------------------------------------------*/
  491.  
  492.    printmsg(0,"%s called by %s at %ld bps using %c protocol",
  493.          nodename,
  494.          hostp->hostname,
  495.          (long) GetSpeed(),
  496.          msg[1]);
  497.  
  498.    assert( hostp != BADHOST );
  499.    hostp->hstatus = inprogress;
  500.    time( &remote_stats.lconnect );
  501.    return CONN_CLIENT;
  502.  
  503. } /*startup_client*/
  504.  
  505. /*--------------------------------------------------------------------*/
  506. /*    s e t p r o t o                                                 */
  507. /*                                                                    */
  508. /*    set the protocol to be used                                     */
  509. /*--------------------------------------------------------------------*/
  510.  
  511. static void setproto(char wanted)
  512. {
  513.    Proto *tproto;
  514.  
  515.    for (tproto = Protolst;
  516.       tproto->type != '\0' && tproto->type != wanted;
  517.       tproto++) {
  518.       printmsg(3, "setproto: wanted '%c', have '%c'", wanted, tproto->type);
  519.    }
  520.  
  521.    if (tproto->type == '\0') {
  522.       printmsg(0, "setproto: You said I have protocol '%c' but I cant find it!",
  523.             wanted);
  524.       panic();
  525.    }
  526.  
  527.    getpkt  = tproto->getpkt;
  528.    sendpkt = tproto->sendpkt;
  529.    openpk  = tproto->openpk;
  530.    closepk = tproto->closepk;
  531.    rdmsg   = tproto->rdmsg;
  532.    wrmsg   = tproto->wrmsg;
  533.    eofpkt  = tproto->eofpkt;
  534.    filepkt = tproto->filepkt;
  535. } /*setproto*/
  536.  
  537. /*
  538.       s c a n d i r
  539.  
  540.       Scan spooling directory for C.* files for the remote host
  541.       (rmtname)
  542.  
  543.       Assumes the parameter remote is from static storage!
  544. */
  545.  
  546. XFER_STATE scandir(char *remote)
  547. {
  548.    static DIR *dirp;
  549.    static char *saveremote = NULL;
  550.    static char remotedir[FILENAME_MAX];
  551.  
  552.    struct direct *dp;
  553.  
  554. /*--------------------------------------------------------------------*/
  555. /*          Determine if we must restart the directory scan           */
  556. /*--------------------------------------------------------------------*/
  557.  
  558.    if (fwork != NULL )
  559.    {
  560.       fclose( fwork );
  561.       fwork = NULL;
  562.    }
  563.  
  564.    if ( (remote == NULL) || (saveremote == NULL ) ||
  565.         !equal(remote, saveremote) )
  566.    {
  567.       if ( saveremote != NULL )  /* Clean up old directory? */
  568.       {                          /* Yes --> Do so           */
  569.          closedir(dirp);
  570.          saveremote = NULL;
  571.       } /* if */
  572.  
  573.       if ( remote == NULL )      /* Clean up only, no new search? */
  574.          return XFER_NOLOCAL;    /* Yes --> Return to caller      */
  575.  
  576.       sprintf(remotedir,"%s/%.8s/C",spooldir,remote);
  577.       if ((dirp = opendir(remotedir)) == nil(DIR))
  578.       {
  579.          printmsg(2, "scandir: couldn't opendir() %s", remotedir);
  580.          return XFER_NOLOCAL;
  581.       } /* if */
  582.  
  583.       saveremote = (char *) remote;
  584.                               /* Flag we have an active search    */
  585.    } /* if */
  586.  
  587. /*--------------------------------------------------------------------*/
  588. /*              Look for the next file in the directory               */
  589. /*--------------------------------------------------------------------*/
  590.  
  591.    if ((dp = readdir(dirp)) != nil(struct direct))
  592.    {
  593.       sprintf(workfile, "%s/%s", remotedir, dp->d_name);
  594.       printmsg(5, "scandir: matched \"%s\"",workfile);
  595.       if ((fwork = FOPEN(workfile, "r", TEXT)) == nil(FILE))
  596.       {
  597.          printmsg(0,"scandir: open failed for %s",workfile);
  598.          saveremote = NULL;
  599.          return XFER_ABORT;   /* Very bad, since we just read its
  600.                                  directory entry!                 */
  601.       }
  602.       else
  603.          return XFER_REQUEST; /* Return success                   */
  604.    }
  605.  
  606. /*--------------------------------------------------------------------*/
  607. /*     No hit; clean up after ourselves and return to the caller      */
  608. /*--------------------------------------------------------------------*/
  609.  
  610.    printmsg(5, "scandir: \"%s\" not matched", remotedir);
  611.    closedir(dirp);
  612.    saveremote = NULL;
  613.    return XFER_NOLOCAL;
  614.  
  615. } /*scandir*/
  616.  
  617. /*
  618.       c a l l e d h o s t
  619.  
  620.       reports true if a host has been called this run, otherwise FALSE
  621.  
  622.       Drew Derbyshire, 18 August 1989
  623.  */
  624.  
  625. boolean calledhost(char *hisremote)
  626. {
  627.    struct HostTable *RmtEntry;
  628.  
  629.    printmsg(8,"calledhost: Checking for host '%s'",hisremote);
  630.    RmtEntry = checkreal(hisremote);
  631.    if ( RmtEntry == BADHOST )
  632.    {
  633.       printmsg(0,"calledhost: Cannot find host \"%s\"",hisremote );
  634.       panic();
  635.    }
  636.    return RmtEntry->called;
  637. }
  638.  
  639.  
  640. /*
  641.    d i d c a l l
  642.  
  643.    sets the flag tested by calledhost to true
  644.  
  645.    Drew Derbyshire, 18 August 1989
  646.  
  647.  */
  648.  
  649. void didcall(char *hisremote)
  650. {
  651.    struct HostTable *RmtEntry;
  652.    printmsg(8,"didcall: host '%s'",hisremote);
  653.    RmtEntry = checkreal(hisremote);
  654.    if ( RmtEntry == BADHOST )
  655.    {
  656.       printmsg(0,"calledhost: Cannot find host \"%s\"",hisremote );
  657.       panic();
  658.    }
  659.    RmtEntry->called = TRUE;
  660. } /* didcall */
  661.